/**************************************************************************
 * Filename	: omx_component_ImageDecoderJpeg.c 			
 *
 * Description	: openmax Jpeg Decoder Component
 *
 * Notes		:                                     
 *
 * Revisions:
 *     Author     		Date     		Version   	 Description
 *     yuyiwei       	2008.10.9 	    1.0.0       
 *   			   
 *********************************************************************/

#include "omxcore.h"
#include "omx_component_ImageDecoderJpeg.h"

//specific include files
#include "jpeg_priv.h"

#include "djpeg_intf.h"

#define MIN(X,Y)    ((X) < (Y) ?  (X) : (Y))

/** Maximum Number of Image Jpeg Decoder Component Instance*/
#define MAX_COMPONENT_JPEG 1

/** a counter of existing instances of jpeg decoder */
OMX_U32 nojpegdecInstance = 0;

/** This is the temporary buffer size used for last portion of input buffer storage */
//#define TEMP_BUFFER_SIZE_IN (10*1024)
#define TEMP_BUFFER_SIZE_IN (4*1024*1024)
#define TEMP_BUFFER_SIZE_OUT (3000*3000*3)

#define OMX_JPEGDEC_DEFAULTCOLORFORMAT  OMX_COLOR_FormatYUV420Planar
    // MX_COLOR_Format24bitRGB888


/* decode frame count for test */
int jpegdeccount = 0;

/*flush cache
  the function must be used before dma transmission*/
//extern VOID cpu_arm926_cache_clean_invalidate_range(OMX_U32 start, OMX_U32 end, OMX_U32 flag);	//flush cache

/***************************************************************************
* Function : omx_ImageDecoderJpeg_LibInit											   
*
* Description : JpegDecoder Codec Init. This function call the 
			omxwin_rcodeca_codecopen to initialize the codec.
*
* Params	:
*																			   
*	Name		                                           Type				            In/Out		Description 						   
*  	omx_jpegdec_component_Private    omx_jpegdec_component_PrivateType	In	   	component private structure
*
* Return : 
*	state returned from omxwin_rcodeca_codecopen
*		  
* Note :
*
* Revision :
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
OMX_ERRORTYPE omx_ImageDecoderJpeg_LibInit(omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private)
{
	OMX_ERRORTYPE err = OMX_ErrorNone;
	
	/* put up the semaphore of the component */
	omx_sem_up(omx_jpegdec_component_Private->JpegSyncSem);

	return err;
}

/***************************************************************************
* Function : omx_ImageDecoderJpeg_LibDeInit											   
*
* Description : JpegDecoder Codec DeInit. 
*
* Params	:
*																			   
*	Name		                                           Type				            In/Out		Description 						   
*  	omx_jpegdec_component_Private    omx_jpegdec_component_PrivateType	In	   	component private structure
*
* Return : 
*
*		  
* Note :
*
* Revision :
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
void omx_ImageDecoderJpeg_LibDeInit(omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private)
{
    /** close the codec */
}

/***************************************************************************
* Function : omx_ImageDecoderJpeg_Constructor											   
*
* Description : JpegDecoder Component Constructor. This function allocates the 
*			 omx_jpegdec_component_PrivateType private structure.
*
* Params	:
*																			   
*	Name		             Type						In/Out		Description 						   
*  	openmaxStandComp    OMX_COMPONENTTYPE*		In/Out	   	Openmax Standard Component structure
*	cComponentName	      OMX_STRING				In			name of the component to be constructed	
*
* Return : 
*	OMX_ErrorInsufficientResources if any ComponentPrivate structure alloc failed
*		  
* Note :
*
* Revision :
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
OMX_ERRORTYPE omx_ImageDecoderJpeg_Constructor(OMX_COMPONENTTYPE *openmaxStandComp, OMX_STRING cComponentName)
{

    OMX_ERRORTYPE err = OMX_ErrorNone;
    omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private;
    OMX_S32 i;

    if (!openmaxStandComp->pComponentPrivate)
    {
        openmaxStandComp->pComponentPrivate = omx_calloc(1, sizeof(omx_jpegdec_component_PrivateType));
        if (openmaxStandComp->pComponentPrivate == NULL)
        {
            return OMX_ErrorInsufficientResources;
        }
    }
    else
    {
        DEBUG(DEB_LEV_FUNCTION_NAME, "In %s, Error Component %x Already Allocated\n", __func__, (int)openmaxStandComp->pComponentPrivate);
    }

    /** we could create our own port structures here
     * fixme maybe the base class could use a "port factory" function pointer?    
     */
    err = omx_base_filter_Constructor(openmaxStandComp, cComponentName);

    /** here we can override whatever defaults the base_component constructor set
     * e.g. we can override the function pointers in the private struct
     */
    omx_jpegdec_component_Private = (omx_jpegdec_component_PrivateType*)openmaxStandComp->pComponentPrivate;

    DEBUG(DEB_LEV_SIMPLE_SEQ, "constructor of jpeg decoder component is called\n");

    /** Allocate Ports and Call base port constructor. */
    if (omx_jpegdec_component_Private->sPortTypesParam.nPorts && !omx_jpegdec_component_Private->ports)
    {
        omx_jpegdec_component_Private->ports = omx_calloc(omx_jpegdec_component_Private->sPortTypesParam.nPorts, sizeof(omx_base_PortType*));
        if (!omx_jpegdec_component_Private->ports)
        {
            return OMX_ErrorInsufficientResources;
        }
        for (i = 0; i < omx_jpegdec_component_Private->sPortTypesParam.nPorts; i++)
        {
            /** this is the important thing separating this from the base class; size of the struct is for derived class port type
             * this could be refactored as a smarter factory function instead?
             */
            omx_jpegdec_component_Private->ports[i] = omx_calloc(1, sizeof(omx_jpegdec_component_PortType));
            if (!omx_jpegdec_component_Private->ports[i])
            {
                return OMX_ErrorInsufficientResources;
            }
        }
    }

    omx_jpegdec_component_Private->PortConstructor(openmaxStandComp, &omx_jpegdec_component_Private->ports[0], 0, OMX_TRUE);
    omx_jpegdec_component_Private->PortConstructor(openmaxStandComp, &omx_jpegdec_component_Private->ports[1], 1, OMX_FALSE);

    /**
     * Domain specific section for the ports.     
     * first we set the parameter common to both formats
     */
   
    //common parameters related to input port
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.eDomain = OMX_PortDomainImage;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.pNativeRender = 0;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.bFlagErrorConcealment = OMX_FALSE;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.eColorFormat = OMX_COLOR_FormatUnused;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.nBufferSize = 50*1024;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.cMIMEType = (OMX_STRING)malloc(sizeof(char)*DEFAULT_MIME_STRING_LENGTH);
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.nFrameWidth = 176; 
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.nFrameHeight = 144; 
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.nStride = 0;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.nSliceHeight = 0;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.pNativeWindow = NULL;

    //common parameters related to output port
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.eDomain = OMX_PortDomainImage;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.pNativeRender = 0;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.bFlagErrorConcealment = OMX_FALSE;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.nBufferSize = 50*1024;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.cMIMEType = (OMX_STRING)malloc(sizeof(char)*DEFAULT_MIME_STRING_LENGTH);
    strcpy(omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.cMIMEType, "raw/image");
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.nFrameWidth = 176; 
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.nFrameHeight = 144; 
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.nStride = 0;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.nSliceHeight = 0;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.pNativeWindow = NULL;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.eCompressionFormat = OMX_IMAGE_CodingUnused;
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.eColorFormat = OMX_JPEGDEC_DEFAULTCOLORFORMAT;

    /** now it's time to know the Image coding type of the component */
    if (!strcmp(cComponentName, IMAGE_DEC_JPEG_NAME))
    {
        omx_jpegdec_component_Private->image_coding_type = OMX_IMAGE_CodingJPEG;
    }
    else if (!strcmp(cComponentName, IMAGE_DEC_BASE_NAME))
    {
        omx_jpegdec_component_Private->image_coding_type = OMX_IMAGE_CodingUnused;
    }
    else
    {
        // IL client specified an invalid component name
        return OMX_ErrorInvalidComponentName;
    }
    /** initialise the semaphore to be used for jpeg decoder access synchronization */
    if (!omx_jpegdec_component_Private->JpegSyncSem)
    {
        omx_jpegdec_component_Private->JpegSyncSem = omx_calloc(1, sizeof(omx_sem));
        if (omx_jpegdec_component_Private->JpegSyncSem == NULL)
        {
            return OMX_ErrorInsufficientResources;
        }
        omx_sem_init(omx_jpegdec_component_Private->JpegSyncSem, 0);
    }

    // default value for private variables
    omx_jpegdec_component_Private->nImgWidth = 0;
    omx_jpegdec_component_Private->nImgHeight = 0;

    /** setting of internal port parameters related to Image format */
    omx_ImageDecoderJpeg_SetInternalParameters(openmaxStandComp);

    /** general configuration irrespective of any Image formats
     *  setting values of other fields of omx_jpegdec_component_Private structure    
     */
    omx_jpegdec_component_Private->JpegReady = OMX_FALSE;
//    omx_jpegdec_component_Private->needSetParam = OMX_FALSE;
    omx_jpegdec_component_Private->BufferMgmtCallback = omx_ImageDecoderJpeg_BufferMgmtCallback;
    omx_jpegdec_component_Private->messageHandler = omx_ImageDecoderJpeg_MessageHandler;
    omx_jpegdec_component_Private->destructor = omx_ImageDecoderJpeg_Destructor;
    openmaxStandComp->SetParameter = omx_ImageDecoderJpeg_SetParameter;
    openmaxStandComp->GetParameter = omx_ImageDecoderJpeg_GetParameter;

    /** increamenting component counter and checking against max allowed components */
    nojpegdecInstance++;

    if (nojpegdecInstance > MAX_COMPONENT_JPEG)
    {
        return OMX_ErrorInsufficientResources;
    }
    return err;
}

/***************************************************************************
* Function : omx_ImageDecoderJpeg_SetInternalParameters											   
*
* Description : This function sets some inetrnal parameters to the input and output port 
*			 depending upon the input and output audio format. 
*
* Params	:
*																			   
*	Name		             Type						In/Out		Description 						   
*  	openmaxStandComp    OMX_COMPONENTTYPE*		In/Out	   	Openmax Standard Component structure
* 	 
* Return:
*
* Note:
*
* Revision:
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
void omx_ImageDecoderJpeg_SetInternalParameters(OMX_COMPONENTTYPE *openmaxStandComp)
{

    omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private;
    omx_jpegdec_component_PortType *pPort,  *outPort;
    
    omx_jpegdec_component_Private = openmaxStandComp->pComponentPrivate;

    /**  setting private fields of outputport */
    pPort = (omx_jpegdec_component_PortType*)omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX];
    setHeader(&pPort->sImageParam, sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE));
    pPort->sImageParam.nPortIndex = 0;
    pPort->sImageParam.nIndex = OMX_IndexParamImagePortFormat;
    pPort->sImageParam.eCompressionFormat = OMX_IMAGE_CodingJPEG;

    /**  setting private fields of outputport */
    outPort = (omx_jpegdec_component_PortType*)omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX];
    setHeader(&outPort->sImageParam, sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE));
    outPort->sImageParam.nPortIndex = 1;
    outPort->sImageParam.nIndex = OMX_IndexParamImagePortFormat;
    outPort->sImageParam.eCompressionFormat = OMX_IMAGE_CodingUnused;
    outPort->sImageParam.eColorFormat = OMX_JPEGDEC_DEFAULTCOLORFORMAT;


    /** setting port & private fields according to Jpeg Image format values */
    strcpy(omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.cMIMEType, "image/jpeg");
    omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]->sPortParam.format.image.eCompressionFormat = OMX_IMAGE_CodingJPEG;

    /**  setting jpeg params */
/*
    setHeader(&omx_jpegdec_component_Private->pImageJpeg, sizeof(OMX_IMAGE_PARAM_JPEGTYPE));
    omx_jpegdec_component_Private->pImageJpeg.nPortIndex = 1;
    omx_jpegdec_component_Private->pImageJpeg.nSliceHeaderSpacing = 0;
    omx_jpegdec_component_Private->pImageJpeg.bSVH = OMX_FALSE;
    omx_jpegdec_component_Private->pImageJpeg.bGov = 0;
    omx_jpegdec_component_Private->pImageJpeg.nPFrames = 15;
    omx_jpegdec_component_Private->pImageJpeg.nBFrames = 0;
    omx_jpegdec_component_Private->pImageJpeg.nIDCVLCThreshold = 0;
    omx_jpegdec_component_Private->pImageJpeg.bACPred = OMX_TRUE;
    omx_jpegdec_component_Private->pImageJpeg.nMaxPacketSize = 10240;
    omx_jpegdec_component_Private->pImageJpeg.nTimeIncRes = 0;
    omx_jpegdec_component_Private->pImageJpeg.eProfile = OMX_IMAGE_JPEGProfileSimple;
    omx_jpegdec_component_Private->pImageJpeg.eLevel = OMX_IMAGE_JPEGLevel1;
    omx_jpegdec_component_Private->pImageJpeg.nAllowedPictureTypes = 0;
    omx_jpegdec_component_Private->pImageJpeg.nHeaderExtension = 1;
    omx_jpegdec_component_Private->pImageJpeg.bReversibleVLC = OMX_TRUE;
*/
    /**  setting ratecontrol params */
 /*   setHeader(&omx_jpegdec_component_Private->rcImageJpeg, sizeof(OMX_IMAGE_PARAM_BITRATETYPE));
    omx_jpegdec_component_Private->rcImageJpeg.nPortIndex = 1;
    omx_jpegdec_component_Private->rcImageJpeg.eControlRate = OMX_Image_ControlRateConstant; 
    omx_jpegdec_component_Private->rcImageJpeg.nTargetBitrate = 48000;        
*/
    /**  setting error correction params */
/*    setHeader(&omx_jpegdec_component_Private->errImageJpeg, sizeof(OMX_IMAGE_PARAM_ERRORCORRECTIONTYPE));
    omx_jpegdec_component_Private->errImageJpeg.nPortIndex = 1;
    omx_jpegdec_component_Private->errImageJpeg.bEnableHEC = OMX_FALSE;
    omx_jpegdec_component_Private->errImageJpeg.bEnableResync = OMX_FALSE;
    omx_jpegdec_component_Private->errImageJpeg.nResynchMarkerSpacing = 0;
    omx_jpegdec_component_Private->errImageJpeg.bEnableDataPartitioning = OMX_FALSE;
    omx_jpegdec_component_Private->errImageJpeg.bEnableRVLC = OMX_TRUE;
*/
    /**  setting motion vector params */
/*    setHeader(&omx_jpegdec_component_Private->mvImageJpeg, sizeof(OMX_IMAGE_PARAM_MOTIONVECTORTYPE));
    omx_jpegdec_component_Private->mvImageJpeg.nPortIndex = 1;
    omx_jpegdec_component_Private->mvImageJpeg.eAccuracy = OMX_Image_MotionVectorHalfPel;
    omx_jpegdec_component_Private->mvImageJpeg.bUnrestrictedMVs = OMX_FALSE;
    omx_jpegdec_component_Private->mvImageJpeg.bFourMV = OMX_TRUE;
    omx_jpegdec_component_Private->mvImageJpeg.sXSearchRange = 16;
    omx_jpegdec_component_Private->mvImageJpeg.sYSearchRange = 16;
*/
    /**  setting quant params */
/*    setHeader(&omx_jpegdec_component_Private->qpImageJpeg, sizeof(OMX_IMAGE_PARAM_QUANTIZATIONTYPE));
    omx_jpegdec_component_Private->qpImageJpeg.nPortIndex = 1;
    omx_jpegdec_component_Private->qpImageJpeg.nQpI = 0;
    omx_jpegdec_component_Private->qpImageJpeg.nQpP = 0;
    omx_jpegdec_component_Private->qpImageJpeg.nQpB = 0;
*/

}


/***************************************************************************
* Function : omx_ImageDecoderJpeg_Destructor											   
*
* Description : Destruct the Jpeg Decoder Component.This function free the input and 
*			 output ports then destruct the compenent.
*
* Params	:
*																			   
*	Name		             Type						In/Out		Description 						   
*  	openmaxStandComp    OMX_COMPONENTTYPE*		In/Out	   	Openmax Standard Component structure
*
* Return:
*
* Note:
*
* Revision:
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
OMX_ERRORTYPE omx_ImageDecoderJpeg_Destructor(OMX_COMPONENTTYPE *openmaxStandComp)
{

    omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private = openmaxStandComp->pComponentPrivate;
    omx_jpegdec_component_PortType *pPort;
    OMX_U32 i;

    /* frees port/s */
    if (omx_jpegdec_component_Private->sPortTypesParam.nPorts && omx_jpegdec_component_Private->ports)
    {
        for (i = 0; i < omx_jpegdec_component_Private->sPortTypesParam.nPorts; i++)
        {
            pPort = (omx_jpegdec_component_PortType*)omx_jpegdec_component_Private->ports[i];
            if (pPort->sPortParam.format.image.cMIMEType != NULL)
            {
                omx_free(pPort->sPortParam.format.image.cMIMEType);
                pPort->sPortParam.format.image.cMIMEType = NULL;
            }
        }
    }
	/** deinitialise the semaphore used for jpeg encoder access synchronization */
    if (omx_jpegdec_component_Private->JpegSyncSem)
    {
        omx_sem_deinit(omx_jpegdec_component_Private->JpegSyncSem);
        omx_free(omx_jpegdec_component_Private->JpegSyncSem);
        omx_jpegdec_component_Private->JpegSyncSem = NULL;
    }

    DEBUG(DEB_LEV_FUNCTION_NAME, "Destructor of jpeg decoder component is called\n");

	/** component destruct */
    omx_base_filter_Destructor(openmaxStandComp);

    nojpegdecInstance--;

    return OMX_ErrorNone;

}

/***************************************************************************
* Function : omx_ImageDecoderJpeg_Init		
*
* Description : The Component Initialization function.
			 This function alloc the tempbuffer for input data
*
* Params	:
*																			   
*	Name		             Type						In/Out		Description 						   
*  	openmaxStandComp    OMX_COMPONENTTYPE*		In/Out	   	Openmax Standard Component structure
*
* Return:
*
* Note:
*
* Revision:
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
OMX_ERRORTYPE omx_ImageDecoderJpeg_Init(OMX_COMPONENTTYPE *openmaxStandComp)
{

    omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private = openmaxStandComp->pComponentPrivate;
    OMX_ERRORTYPE err = OMX_ErrorNone;
    OMX_U8 offset;
    /** initializing omx_jpegdec_component_Private->temporary_buffer_in */
    omx_jpegdec_component_Private->temporary_buffer_in = (OMX_BUFFERHEADERTYPE*)omx_calloc(1, sizeof(OMX_BUFFERHEADERTYPE));
    omx_jpegdec_component_Private->pTempBuffer = (OMX_U8*)omx_calloc(1,TEMP_BUFFER_SIZE_IN);

	/* align the buffer to 4 byte for dma */
	omx_jpegdec_component_Private->temporary_buffer_in->pBuffer = (OMX_U8*)((OMX_U32)(omx_jpegdec_component_Private->pTempBuffer+3)&0xfffffffc);
    omx_jpegdec_component_Private->temporary_buffer_in->nFilledLen = 0;
    omx_jpegdec_component_Private->temporary_buffer_in->nOffset = 0;

	// output buffer
	omx_jpegdec_component_Private->temporary_buffer_out = (OMX_BUFFERHEADERTYPE*)omx_calloc(1, sizeof(OMX_BUFFERHEADERTYPE));
	omx_jpegdec_component_Private->pTempOutBuffer = (OMX_U8*)omx_calloc(1,TEMP_BUFFER_SIZE_OUT);

	omx_jpegdec_component_Private->temporary_buffer_out->pBuffer = (OMX_U8*)((OMX_U32)(omx_jpegdec_component_Private->pTempOutBuffer+3)&0xfffffffc);
	omx_jpegdec_component_Private->temporary_buffer_out->nFilledLen = 0;
	omx_jpegdec_component_Private->temporary_buffer_out->nOffset = 0;


	omx_jpegdec_component_Private->nJpegInState = 0;
	omx_jpegdec_component_Private->nJpegStreamPos = 0;

	omx_jpegdec_component_Private->nJpegOutState = 0;


    return err;
}

/***************************************************************************
* Function : omx_ImageDecoderJpeg_Deinit											   
*
* Description : The CopDeinitialization function.
*
* Params	:
*																			   
*	Name		             Type						In/Out		Description 						   
*  	openmaxStandComp    OMX_COMPONENTTYPE*		In/Out	   	Openmax Standard Component structure
* 
* Return:
*
* Note:
*	 
* Revision:
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
OMX_ERRORTYPE omx_ImageDecoderJpeg_Deinit(OMX_COMPONENTTYPE *openmaxStandComp)
{

    omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private = openmaxStandComp->pComponentPrivate;
    OMX_ERRORTYPE err = OMX_ErrorNone;

    if (omx_jpegdec_component_Private->JpegReady)
    {
    	omx_ImageDecoderJpeg_LibDeInit(omx_jpegdec_component_Private);
        omx_jpegdec_component_Private->JpegReady = OMX_FALSE;
    }

    /*Restore temporary input buffer pointer*/
    DEBUG(DEB_LEV_ERR, "Freeing Temporary Buffer\n");
    /* freeing temporary memory allocation */
    omx_free(omx_jpegdec_component_Private->pTempBuffer);
    omx_jpegdec_component_Private->temporary_buffer_in->pBuffer = NULL;
    omx_free(omx_jpegdec_component_Private->temporary_buffer_in);
    omx_jpegdec_component_Private->temporary_buffer_in = NULL;

    return err;
}

/***************************************************************************
* Function : omx_ImageDecoderJpeg_BufferMgmtCallback		
*
* Description : This function is the buffer management callback function for Jpeg encoding
* 			 is used to process the input buffer and provide one output buffer
*
* Params	:
*																			   
*	Name		             Type						In/Out		Description 						   
*  	openmaxStandComp    OMX_COMPONENTTYPE*		In/Out	   	Openmax Standard Component structure
*	inputbuffer	      	      OMX_BUFFERHEADERTYPE*	In/Out		the input buffer containing the input Jpeg content
*	outputbuffer		      OMX_BUFFERHEADERTYPE*	In/Out		the output buffer on which the output pcm content will be written
*
* Return:
*	OMX_ErrorInsufficientResources if any ComponentPrivate structure alloc failed
*
* Note:
*	 
* Revision:
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
int ConvertYUVToUYVY(unsigned char *pBuf, int nWidth, int nHeight)
{
	unsigned char *p = pBuf;
	unsigned char *pDst = p;
	int i, j;
	int nHalfWidth = nWidth / 2;

	if (nWidth % 2 != 0)
	{
		return -1;
	}

	for (i = 0; i < nHeight; i++)
	{
		for (j = 0; j < nHalfWidth; j++)
		{
			unsigned char y1 = p[0];
			unsigned char u1 = p[1];
			unsigned char v1 = p[2];
			unsigned char y2 = p[3];
			unsigned char u2 = p[4];
			unsigned char v2 = p[5];

			pDst[0] = (u1 + u2 + 1) / 2;
			pDst[1] = y1;
			pDst[2] = (v1 + v2 + 1) / 2;
			pDst[3] = y2;

			pDst += 4;
			p += 6;
		}
	}

	return 0;
}

void omx_ImageDecoderJpeg_BufferMgmtCallback(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE *inputbuffer, OMX_BUFFERHEADERTYPE *outputbuffer)
{
    omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private = openmaxStandComp->pComponentPrivate;
    int consumed = 0;
    int nsamples;
    int tocopy;
    int status = 0;
    Jpeg_inbuffer Jpeg_INBuf;
    Jpeg_outbuffer Jpeg_OUTBuf;
    int endOfSeq = 0;

	int nTempBufRest = 0;
	int iEndOfs = 0;
	
	OMX_BUFFERHEADERTYPE *pTempBufIn = omx_jpegdec_component_Private->temporary_buffer_in;
	OMX_BUFFERHEADERTYPE *pTempBufOut = omx_jpegdec_component_Private->temporary_buffer_out;

	nTempBufRest = TEMP_BUFFER_SIZE_IN - omx_jpegdec_component_Private->temporary_buffer_in->nFilledLen;
	
    /* move data to tempbuffer */
    if(nTempBufRest > 0)
    {
   		tocopy = MIN(inputbuffer->nFilledLen, nTempBufRest);
        memcpy(pTempBufIn->pBuffer + pTempBufIn->nFilledLen, 
			inputbuffer->pBuffer + inputbuffer->nOffset, tocopy);
        pTempBufIn->nFilledLen += tocopy;
		inputbuffer->nFilledLen -= tocopy;
		inputbuffer->nOffset += tocopy;
    }
	else if (omx_jpegdec_component_Private->nJpegInState >= 2)
	{	// the header is fixed and the buffer cannot hold any more data
		// error
		inputbuffer->nFilledLen = 0;
		inputbuffer->nOffset = 0;
		outputbuffer->nFilledLen = 0;
		inputbuffer->nOffset = 0;
		omx_jpegdec_component_Private->nJpegInState = 0;
		return;
	}

	// check for JPEG header and tail

	// find header
	if (omx_jpegdec_component_Private->nJpegInState == 0 && 
		pTempBufIn->nFilledLen > 0)
	{
		OMX_U8 *pBuffer = pTempBufIn->pBuffer;

		// find header
		int iHeaderOfs = -1;
		int i;
		for (i = 0; i < pTempBufIn->nFilledLen - 2; i++)
		{
			if (pBuffer[i] == 0xff && pBuffer[i + 1] == 0xD8 && pBuffer[i+2] == 0xff)
			{
				iHeaderOfs = i;
				break;
			}
		}

		if (iHeaderOfs < 0)
		{	// no valid header found

			// remove all the stream that is not to be used
			pTempBufIn->nOffset = 0;
			pTempBufIn->nFilledLen = 2;
			pBuffer[0] = pBuffer[pTempBufIn->nFilledLen - 2];
			pBuffer[1] = pBuffer[pTempBufIn->nFilledLen - 1];

			// outputbuffer remains unchanged
			return;
		}

		memcpy(pBuffer, pBuffer + iHeaderOfs, pTempBufIn->nFilledLen - iHeaderOfs);
		pTempBufIn->nFilledLen = pTempBufIn->nFilledLen - iHeaderOfs;
		pTempBufIn->nOffset = 0;


		omx_jpegdec_component_Private->nJpegInState = 2;	// header found
		omx_jpegdec_component_Private->nJpegStreamPos = 2;		// prepare for finding the tail
	}

	// find tail
	if (omx_jpegdec_component_Private->nJpegInState >= 2)
	{
		OMX_U8 *pBuffer = pTempBufIn->pBuffer;

		int iTailOfs = -1;
		int i;
		for (i = omx_jpegdec_component_Private->nJpegStreamPos; i < pTempBufIn->nFilledLen - 1; )
		{
			if (pBuffer[i] == 0xff && pBuffer[i + 1] == 0xD8)
			{
				if (i < pTempBufIn->nFilledLen - 3 && pBuffer[i+2] == 0xff)
				{
					omx_jpegdec_component_Private->nJpegInState++;
					i += 2;
				}
				else
				{
					omx_jpegdec_component_Private->nJpegStreamPos = i;

					if (i < pTempBufIn->nFilledLen - 3)
					{
						i += 3;	// because pBuffer[i+2] is not 0xff, no need to check it
					}
					else
					{
						break;
					}
				}
			}
			else if (pBuffer[i] == 0xff && pBuffer[i + 1] == 0xD9)
			{
				omx_jpegdec_component_Private->nJpegInState--;
				if (omx_jpegdec_component_Private->nJpegInState == 1)
				{	// found
					iTailOfs = i;
					break;
				}
				i += 2;
			}
			else
			{
				i++;
			}
		}

		omx_jpegdec_component_Private->nJpegStreamPos = i;

		if (iTailOfs < 0)
		{	// not found
			return;
		}

		iEndOfs = iTailOfs + 2;
	}

	if (omx_jpegdec_component_Private->nJpegInState == 1 && 
		omx_jpegdec_component_Private->nJpegOutState == 0)
	{	// to decode
		int nImgWidth, nImgHeight;

		OMX_U8 * pSrc = (OMX_U8 *)pTempBufIn->pBuffer;
		OMX_U32 nSrcLen = iEndOfs;
		OMX_U8 * pDst = (OMX_U8 *)pTempBufOut->pBuffer;
		OMX_U32 nDstLen = 0;

		JPEGDEC stJpegDec;

		jpegdec_Init(&stJpegDec);

		if (omx_jpegdec_component_Private->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.format.image.eColorFormat != OMX_COLOR_FormatYUV420Planar)
		{
			return; // color format not supported
		}

		jpegdec_SetOutputColorSpace(&stJpegDec, JCS_YCbCr);   // default

		jpegdec_Predecode(&stJpegDec, pSrc, nSrcLen);
		jpegdec_GetImageSize(&stJpegDec, &nImgWidth, &nImgHeight);
		jpegdec_Decode(&stJpegDec, pDst);
		jpegdec_Deinit(&stJpegDec);

		ConvertYUVToUYVY(pDst, nImgWidth, nImgHeight);


		pTempBufOut->nOffset = 0;
		nDstLen = pTempBufOut->nFilledLen = 
			nImgWidth * nImgHeight * 2;

		omx_jpegdec_component_Private->nImgWidth = nImgWidth;
		omx_jpegdec_component_Private->nImgHeight = nImgHeight;

		// remove the stream having been decoded in the temp buffer
		memcpy(pTempBufIn->pBuffer, pTempBufIn->pBuffer + iEndOfs, pTempBufIn->nFilledLen - iEndOfs);
		pTempBufIn->nFilledLen -= iEndOfs;
		omx_jpegdec_component_Private->nJpegStreamPos = 0;


		omx_jpegdec_component_Private->nJpegInState = 0;
		omx_jpegdec_component_Private->nJpegOutState = 1;

	}

	if (omx_jpegdec_component_Private->nJpegOutState > 0)
	{
		int outBufRest = outputbuffer->nAllocLen - (outputbuffer->nFilledLen + outputbuffer->nOffset);
		int nTempRest = pTempBufOut->nFilledLen;

		if (outBufRest < nTempRest)
		{
			memcpy(outputbuffer->pBuffer + outputbuffer->nOffset + outputbuffer->nFilledLen, 
				pTempBufOut->pBuffer 
				+ pTempBufOut->nOffset, 
				outBufRest);

			outputbuffer->nFilledLen += outBufRest;

			pTempBufOut->nOffset += outBufRest;
			pTempBufOut->nFilledLen -= outBufRest;

			jpegdeccount++;
			return;
		}
		else
		{
			memcpy(outputbuffer->pBuffer + outputbuffer->nOffset + outputbuffer->nFilledLen, 
				pTempBufOut->pBuffer + pTempBufOut->nOffset, 
				nTempRest);

			outputbuffer->nFilledLen += nTempRest;

			pTempBufOut->nOffset = 0;
			pTempBufOut->nFilledLen = 0;
			omx_jpegdec_component_Private->nJpegOutState = 0;	// restore the state to find header again in the following decoding

		}

	}

    //printk("decode count:%d \n",jpegdeccount);
    /* update tempbuffer data length */

    /* update outputbuffer data length */
	/* move the data to the beginning of the outputbuffer 
	    if the outputbuffer isn't aligned to 4byte*/

    
    DEBUG(DEB_LEV_SIMPLE_SEQ, "Returning output buffer size=%d \n", (int)Jpeg_OUTBuf.nFilledSize);

	return;
}

/***************************************************************************
* Function : omx_ImageDecoderJpeg_SetParameter											   
*
* Description : this function sets the parameter values regarding audio format & index
*
* Params	:
*																			   
*	Name		             			Type				In/Out		Description 						   
*  	hComponent    				OMX_HANDLETYPE		Out	   		Component Handle
*	nParamIndex	      				OMX_INDEXTYPE		In			Parameter Index	
* 	ComponentParameterStructure 	OMX_PTR				In			Component Parameter Structure
*
* Return:
*	OMX_ErrorBadParameter if there is no Parameter structure or the parameter is not for this component role	
*	OMX_ErrorBadPortIndex if portindex is wrong
*
* Note:
*
* Revision:
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
OMX_ERRORTYPE omx_ImageDecoderJpeg_SetParameter(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nParamIndex, OMX_IN OMX_PTR ComponentParameterStructure)
{

    OMX_ERRORTYPE err = OMX_ErrorNone;
    OMX_IMAGE_PARAM_PORTFORMATTYPE *pImagePortFormat;
    OMX_PARAM_COMPONENTROLETYPE *pComponentRole;
    OMX_U32 portIndex;

    /* Check which structure we are being fed and make control its header */
    OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE*)hComponent;
    omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private = openmaxStandComp->pComponentPrivate;
    omx_jpegdec_component_PortType *port;
    if (ComponentParameterStructure == NULL)
    {
    	/** no parameter structure */
        return OMX_ErrorBadParameter;
    }

    DEBUG(DEB_LEV_SIMPLE_SEQ, "   Setting parameter %i\n", nParamIndex);
    switch (nParamIndex)
    {
        case OMX_IndexParamImagePortFormat:
            pImagePortFormat = (OMX_IMAGE_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
            portIndex = pImagePortFormat->nPortIndex;
            /*Check Structure Header and verify component state*/
            err = omx_base_component_ParameterSanityCheck(hComponent, portIndex, pImagePortFormat, sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE));
            if (err != OMX_ErrorNone)
            {
                DEBUG(DEB_LEV_ERR, "In %s Parameter Check Error=%x\n", __func__, err);
                break;
            }
            if (portIndex <= 1)
            {
            	/** set the parameter to omx_jpegenc_component_PortType structure */
                port = (omx_jpegdec_component_PortType*)omx_jpegdec_component_Private->ports[portIndex];
                memcpy(&port->sImageParam, pImagePortFormat, sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE));
            }
            else
            {
                return OMX_ErrorBadPortIndex;
            }
            break;
            
        case OMX_IndexParamStandardComponentRole:
            pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)ComponentParameterStructure;
            if (!strcmp((char*)pComponentRole->cRole, IMAGE_DEC_JPEG_ROLE))
            {
                omx_jpegdec_component_Private->image_coding_type = OMX_IMAGE_CodingJPEG;
            }
            else
            {
                return OMX_ErrorBadParameter;
            }
            omx_ImageDecoderJpeg_SetInternalParameters(openmaxStandComp);
            break;
			
        default:
            /*Call the base component function*/
            return omx_base_component_SetParameter(hComponent, nParamIndex, ComponentParameterStructure);
    }

    return err;

}

/***************************************************************************
* Function : omx_ImageDecoderJpeg_GetParameter		
*
* Description :  this function gets the parameters regarding audio formats and index.
*
* Params	:
*																			   
*	Name		             			Type				In/Out		Description 						   
*  	hComponent    				OMX_HANDLETYPE		In	   		Component Handle
*	nParamIndex	      				OMX_INDEXTYPE		In			Parameter Index	
* 	ComponentParameterStructure 	OMX_PTR				Out			Component Parameter Structure to return
*
* Return:
*	OMX_ErrorBadParameter if there is no Parameter structure
*	OMX_ErrorBadPortIndex if portindex is wrong
*
* Note:
*	 
* Revision:
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
OMX_ERRORTYPE omx_ImageDecoderJpeg_GetParameter(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nParamIndex, OMX_INOUT OMX_PTR ComponentParameterStructure)
{

    OMX_IMAGE_PARAM_PORTFORMATTYPE *pImagePortFormat;
    OMX_PARAM_COMPONENTROLETYPE *pComponentRole;
    omx_jpegdec_component_PortType *port;
    OMX_ERRORTYPE err = OMX_ErrorNone;

    OMX_COMPONENTTYPE *openmaxStandComp = (OMX_COMPONENTTYPE*)hComponent;
    omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private = openmaxStandComp->pComponentPrivate;
    if (ComponentParameterStructure == NULL)
    {
    	/** no parameter structure */
        return OMX_ErrorBadParameter;
    }
    DEBUG(DEB_LEV_SIMPLE_SEQ, "   Getting parameter %i\n", nParamIndex);
    /* Check which structure we are being fed and fill its header */

    
    switch (nParamIndex)
    {
        case OMX_IndexParamImageInit:
			/*Check Structure Header and verify component state*/
            if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PORT_PARAM_TYPE))) != OMX_ErrorNone)
            {
                break;
            }
            memcpy(ComponentParameterStructure, &omx_jpegdec_component_Private->sPortTypesParam, sizeof(OMX_PORT_PARAM_TYPE));
            break;

        case OMX_IndexParamImagePortFormat:
            pImagePortFormat = (OMX_IMAGE_PARAM_PORTFORMATTYPE*)ComponentParameterStructure;
			/*Check Structure Header and verify component state*/
            if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE))) != OMX_ErrorNone)
            {
                break;
            }
            if (pImagePortFormat->nPortIndex <= 1)
            {
                port = (omx_jpegdec_component_PortType*)omx_jpegdec_component_Private->ports[pImagePortFormat->nPortIndex];
                memcpy(pImagePortFormat, &port->sImageParam, sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE));
            }
            else
            {
                return OMX_ErrorBadPortIndex;
            }
            break;

        case OMX_IndexParamStandardComponentRole:
            pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)ComponentParameterStructure;
            if ((err = checkHeader(ComponentParameterStructure, sizeof(OMX_PARAM_COMPONENTROLETYPE))) != OMX_ErrorNone)
            {
                break;
            }
            if (omx_jpegdec_component_Private->image_coding_type == OMX_IMAGE_CodingJPEG)
            {
                strcpy((char*)pComponentRole->cRole, IMAGE_DEC_JPEG_ROLE);
            }
            else
            {
                strcpy((char*)pComponentRole->cRole, "\0");
            }
            break;
			
        default:
            /*Call the base component function*/
            return omx_base_component_GetParameter(hComponent, nParamIndex, ComponentParameterStructure);
    }
    return OMX_ErrorNone;

}

/***************************************************************************
* Function : omx_ImageDecoderJpeg_MessageHandler	
*
* Description : message handling of Jpeg encoder.
*
* Params	:
*																			   
*	Name		             Type						In/Out		Description 						   
*  	openmaxStandComp    OMX_COMPONENTTYPE		In/Out	   	Openmax Standard Component structure
*	message	      		      internalRequestMessageType	In			internal Message Type	
*
* Return:
*	OMX_ErrorInsufficientResources if any ComponentPrivate structure alloc failed
*
* Note:
*	 
* Revision:
*
*     Author     		Date     		Version   	 Description
*     yuyiwei       	2008.10.9 	    1.0.0       
*									   
***************************************************************************/
OMX_ERRORTYPE omx_ImageDecoderJpeg_MessageHandler(OMX_COMPONENTTYPE *openmaxStandComp, internalRequestMessageType *message)
{

    omx_jpegdec_component_PrivateType *omx_jpegdec_component_Private = (omx_jpegdec_component_PrivateType*)openmaxStandComp->pComponentPrivate;
    OMX_ERRORTYPE err = OMX_ErrorNone;
    OMX_STATETYPE eCurrentState = omx_jpegdec_component_Private->state;
    DEBUG(DEB_LEV_SIMPLE_SEQ, "In %s\n", __func__);

    if (message->messageType == OMX_CommandStateSet)
    {
        if ((message->messageParam == OMX_StateIdle) && (omx_jpegdec_component_Private->state == OMX_StateLoaded))
        {
        	/** state loaded to state idle and initialise the compenent */
            err = omx_ImageDecoderJpeg_Init(openmaxStandComp);
            if (err != OMX_ErrorNone)
            {
                DEBUG(DEB_LEV_ERR, "In %s Jpeg Decoder Init Failed Error=%x\n", __func__, err);
                return err;
            }
        }
        else if ((message->messageParam == OMX_StateExecuting) && (omx_jpegdec_component_Private->state == OMX_StateIdle))
        {
        	/** state idle to state executing and up the synchronization semaphore*/
            DEBUG(DEB_LEV_FULL_SEQ, "State Changing from Idle to Exec\n");
			/** initialise the tempbuffer */
            omx_jpegdec_component_Private->temporary_buffer_in->nFilledLen = 0;
            omx_jpegdec_component_Private->temporary_buffer_in->nOffset = 0;            
			if (!omx_jpegdec_component_Private->JpegReady)
            {
                //omx_sem_up(omx_jpegdec_component_Private->JpegSyncSem);
                err = omx_ImageDecoderJpeg_LibInit(omx_jpegdec_component_Private);
                if (err != OMX_ErrorNone)
                {
                    return OMX_ErrorNotReady;
                }
                omx_jpegdec_component_Private->JpegReady = OMX_TRUE;
            }
        }
    }
    /** Execute the base message handling */
    err = omx_base_component_MessageHandler(openmaxStandComp, message);

    if (message->messageType == OMX_CommandStateSet)
    {
        if ((message->messageParam == OMX_StateLoaded) && (eCurrentState == OMX_StateIdle))
        {
        	/** state idle to state loaded and deinitialise the compenent */
            err = omx_ImageDecoderJpeg_Deinit(openmaxStandComp);
            if (err != OMX_ErrorNone)
            {
                DEBUG(DEB_LEV_ERR, "In %s Jpeg Decoder Deinit Failed Error=%x\n", __func__, err);
                return err;
            }
        }
        else if ((message->messageParam == OMX_StateIdle) && (eCurrentState == OMX_StateExecuting))
        {
        	/** state executing to state idle */
            omx_ImageDecoderJpeg_LibDeInit(omx_jpegdec_component_Private);
            omx_jpegdec_component_Private->JpegReady = OMX_FALSE;
        }
    }

    return err;
}

